package conf

import (
	"bytes"
	"fmt"
	"github.com/spf13/viper"
	"io/ioutil"
	"os"
)

//全局变量
var (
	IConfBase     *BaseConf
	IConfRedisMap *RedisMapConf
	IConfMySQLMap *MySQLMapConf
)

/* =================================================================
	其实不用定义结构体 也可以直接读取配置文件的值
	但是，这样的话，每次都要 lib.GetStringConf("xxx.xxx.xxxxx") 这样获取
	对于系统一些常规经常使用的配置，定义结构体 初始化后 可以直接 调用 就方便很多
	注意 这里 的 结构体 必须 base.toml一一对应
 * =================================================================*/

//================================== BaseConf =================================
func InitBaseConf(path string) error {
	IConfBase = &BaseConf{}
	err := parseConfigToType(getTomlConfFilePath(path), IConfBase)
	if err != nil {
		return err
	}
	return nil
}

type BaseConf struct {
	Base struct {
		DebugMode    string `mapstructure:"debug_mode"`
		TimeLocation string `mapstructure:"time_location"`
	} `mapstructure:"base"`
	Http struct {
		Addr           string `mapstructure:"addr"`
		ReadTimeout    int    `mapstructure:"read_timeout"`
		WriteTimeout   int    `mapstructure:"write_timeout"`
		MaxHeaderBytes int    `mapstructure:"max_header_bytes"`
	} `mapstructure:"http"`
}

//================================== RedisConf =================================
// 访问案例：lib.IConfRedisMap.List["pro"].ProxyList
func InitRedisConf(path string) error {
	IConfRedisMap = &RedisMapConf{}
	err := parseConfigToType(getTomlConfFilePath(path), IConfRedisMap)
	if err != nil {
		return err
	}
	return nil
}

type RedisConf struct {
	ProxyList    []string `mapstructure:"proxy_list"`
	Password     string   `mapstructure:"password"`
	Db           int      `mapstructure:"db"`
	ConnTimeout  int      `mapstructure:"conn_timeout"`
	ReadTimeout  int      `mapstructure:"read_timeout"`
	WriteTimeout int      `mapstructure:"write_timeout"`
}

type RedisMapConf struct {
	List map[string]*RedisConf `mapstructure:"list"`
}

//================================== MySQLMapConf 系列=================================
func InitMySQLConf(path string) error {
	IConfMySQLMap = &MySQLMapConf{}
	err := parseConfigToType(getTomlConfFilePath(path), IConfMySQLMap)
	if err != nil {
		return err
	}
	return nil
}

type MySQLMapConf struct {
	List map[string]*MySQLConf `mapstructure:"list"`
}

type MySQLConf struct {
	DriverName      string `mapstructure:"driver_name"`
	DataSourceName  string `mapstructure:"data_source_name"`
	MaxOpenConn     int    `mapstructure:"max_open_conn"`
	MaxIdleConn     int    `mapstructure:"max_idle_conn"`
	ConnMaxLifeTime int    `mapstructure:"conn_max_life_time"`
}

/* =================================================================
	============= 解析工具 ============
	解析配置 到 自定义 type
	configFilePath  全路径文件名
 * =================================================================*/
func parseConfigToType(configFilePath string, conf interface{}) error {
	file, err := os.Open(configFilePath)
	if err != nil {
		return fmt.Errorf("Open config file %v fail, %v", configFilePath, err)
	}

	data, err := ioutil.ReadAll(file)
	if err != nil {
		return fmt.Errorf("Read config fail, %v", err)
	}

	viper := viper.New()
	viper.SetConfigType("toml")
	viper.ReadConfig(bytes.NewBuffer(data))
	if err := viper.Unmarshal(conf); err != nil {
		return fmt.Errorf("Parse config fail, config:%v, err:%v", string(data), err)
	}

	return nil
}

/* =================================================================
	获取toml配置文件的路径 全路径地址
	eg: return "conf/dev/base.toml"
 * =================================================================*/
func getTomlConfFilePath(fileName string) string {
	return IConfEnvPath + "/" + fileName + ".toml"
}
